/**
 * <h3>ThemeMapper</h3>
 * <p> 大赛信息数据访问层接口 </p>
 *
 * <h3>功能描述</h3>
 * <p> 定义对数据库表 theme_competition 的基本操作方法，包括增删改查 </p>
 * <p> 配合 MyBatis Plus 实现 ORM 映射与持久化操作 </p>
 *
 * <h3>元数据</h3>
 * <ul>
 *     <li> 作者：郭强 </li>
 *     <li> 创建日期：2025年05月18日 14:20:15 </li>
 * </ul>
 *
 * <h3>其他信息</h3>
 * <ul>
 *     <li> 继承自：{@link BaseMapper<ThemeDTO>} </li>
 *     <li> 示例代码：{@code List<Theme> list = themeMapper.selectThemeList(dto);} </li>
 * </ul>
 *
 * @apiNote 方法签名应与 XML 文件中的 id 保持一致，以确保正确绑定
 * @implSpec 使用泛型类型 ThemeDTO 进行实体映射
 * @since v1.0.0.0
 */
package com.dnndo.system.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dnndo.common.core.domain.entity.SysRole;
import com.dnndo.common.core.domain.entity.SysUser;
import com.dnndo.common.utils.SecurityUtils;
import com.dnndo.system.domain.dto.ThemeDTO;
import com.dnndo.system.domain.dto.ThemeInfoDTO;
import com.dnndo.system.domain.dto.ThemeQueryDTO;
import com.dnndo.system.domain.dto.WorkDTO;
import com.dnndo.system.domain.vo.*;
import com.dnndo.system.mapper.SysRoleMapper;
import com.dnndo.system.mapper.SysUserMapper;
import com.dnndo.system.mapper.ThemeMapper;
import com.dnndo.system.service.ThemeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 大赛服务实现类
 */
@Service
public class ThemeServiceImpl extends ServiceImpl<ThemeMapper, ThemeDTO> implements ThemeService {

    private final ThemeMapper themeMapper;

    private final SysRoleMapper sysRoleMapper;

    private final SysUserMapper sysUserMapper;

    @Autowired
    public ThemeServiceImpl(ThemeMapper themeMapper,  SysRoleMapper sysRoleMapper, SysUserMapper sysUserMapper) {
        this.themeMapper = themeMapper;
        this.sysRoleMapper = sysRoleMapper;
        this.sysUserMapper = sysUserMapper;
    }

    /**
     * 查询大赛主题列表（按用户角色分支）
     * 逻辑说明：
     * 1. 获取当前用户的角色Key集合（如school、common、admin）。
     * 2. school和common角色需设置用户所属学校ID，实现数据隔离。
     * 3. 查询主题列表后，标记属于当前用户的主题（mySelf）。
     *
     * @param dto 查询条件，包含用户ID、学校ID等
     * @return List<ThemeDTO> 主题信息列表
     */
    @Override
    public List<ThemeDTO> selectThemeList(ThemeDTO dto) {
        List<String> roleKeys = getUserRoleKeys(dto.getUserId());
        Integer userId = dto.getUserId();
        if (roleKeys.contains("school") || roleKeys.contains("common")) {
            setUserSchoolId(dto);
        }
        List<ThemeDTO> themeList = themeMapper.selectThemeList(dto);
        for (ThemeDTO list : themeList){
            if (list.getUserId() != null && list.getUserId().equals(userId))
                list.setMySelf("true");
        }
        return themeList;
    }

    /**
     * 获取指定用户的角色Key集合
     * 逻辑说明：
     * 1. 通过用户ID查询其所有角色。
     * 2. 提取所有角色的roleKey，返回字符串列表。
     *
     * @param userId 用户ID
     * @return List<String> 角色Key列表
     */
    private List<String> getUserRoleKeys(Integer userId) {
        List<SysRole> roles = sysRoleMapper.selectRolePermissionByUserId(userId.longValue());
        return roles.stream().map(SysRole::getRoleKey).toList();
    }

    /**
     * 设置用户所属学校ID到DTO
     * 逻辑说明：
     * 1. 通过用户ID查询用户信息。
     * 2. 将用户的schoolId赋值到DTO，便于后续按学校隔离数据。
     *
     * @param dto 主题DTO，需包含userId
     */
    private void setUserSchoolId(ThemeDTO dto) {
        SysUser user = sysUserMapper.selectUserById(dto.getUserId().longValue());
        dto.setSchoolId(Integer.valueOf(user.getSchoolId()));
    }

    /**
     * 根据主题ID查询主题详情
     * 逻辑说明：
     * 1. 通过themeId查询主题详细信息。
     *
     * @param themeId 主题ID
     * @return ThemeDTO 主题详情
     */
    @Override
    public ThemeDTO selectThemeById(Long themeId) {
        return themeMapper.selectThemeListById(themeId);
    }

    /**
     * 新增主题信息
     * 逻辑说明：
     * 1. 插入新的主题数据，需保证dto字段完整。
     *
     * @param dto 主题数据对象
     * @return int 受影响的记录数
     */
    @Override
    public int insertTheme(ThemeDTO dto) {
        return themeMapper.insertTheme(dto);
    }

    /**
     * 更新主题信息
     * 逻辑说明：
     * 1. 根据dto中的themeId更新主题信息。
     *
     * @param dto 主题数据对象
     * @return int 受影响的记录数
     */
    @Override
    public int updateThemeById(ThemeDTO dto) {
        return themeMapper.updateThemeById(dto);
    }

    /**
     * 删除指定ID的主题信息
     * 逻辑说明：
     * 1. 根据themeId删除对应主题信息。
     *
     * @param themeId 主题ID
     * @return int 受影响的记录数
     */
    @Override
    public int deleteThemeById(Integer themeId) {
        return themeMapper.deleteThemeById(themeId);
    }

    /**
     * 查询主题大赛信息（支持中英文）
     * 逻辑说明：
     * 1. 获取当前用户ID，若获取失败视为未登录。
     * 2. 根据params.language分支，分别查询中文或英文主题大赛信息。
     * 3. 返回组装好的主题大赛VO列表。
     *
     * @param params 查询参数，包含语言类型
     * @return List<ThemeInfoVO> 主题大赛信息列表
     */
    public List<ThemeInfoVO> competition(ThemeInfoDTO params) {
        List<ThemeInfoVOZH> listZH ;
        List<ThemeInfoVOEN> listEN ;
        // 获取当前用户ID
        Integer userId = null;
        try {
            userId = SecurityUtils.getUserId().intValue();
        } catch (Exception e) {
            log.warn("获取用户ID异常，将视为未登录用户"+ e.getMessage());
        }
        if (params == null) {
            throw new IllegalArgumentException("参数 'params' 不能为空");
        }
        if ("en".equalsIgnoreCase(params.getLanguage())) {
            listEN = themeMapper.competitionEn(userId, params.getSchoolId());
            return new ArrayList<>(listEN);
        }
        listZH = themeMapper.competition(userId,params.getSchoolId());
        return new ArrayList<>(listZH);
    }

    /**
     * 查询主题大赛详情（支持中英文）
     * 逻辑说明：
     * 1. 根据dto.language分支，分别查询中文或英文主题大赛详情。
     * 2. 安全获取用户ID，失败时设为null。
     * 3. 返回组装好的主题大赛详情VO。
     *
     * @param dto 查询参数，包含主题ID和语言类型
     * @return ThemeQueryVO 主题大赛详情
     */
    @Override
    public ThemeQueryVO theme(ThemeQueryDTO dto) {
        ThemeQueryVO list;
        ThemeQueryVOZH listZH;
        ThemeQueryVOEN listEN;
        Integer themeId = dto.getThemeId();
        String language =  dto.getLanguage();
        // 安全获取用户ID，失败时设为null
        Integer userId = null;
        try {
            userId = SecurityUtils.getUserId().intValue();
        } catch (Exception e) {
            log.warn("获取用户ID异常，将视为未登录用户"+ e.getMessage());
        }
        if ("en".equalsIgnoreCase(language)) {
            listEN = themeMapper.themeEn(themeId,userId);
            list = listEN;
            return list;
        }
        listZH = themeMapper.theme(themeId,userId);
        list = listZH;
        return list;
    }

    /**
     * 查询当前主题大赛的所有作品（支持中英文）
     * 逻辑说明：
     * 1. 根据params.language分支，分别查询中文或英文作品列表。
     * 2. 对每个作品的opusUrls字段进行分割，组装为List<String>。
     * 3. 返回组装好的作品列表。
     *
     * @param params 查询参数，包含主题ID和语言类型
     * @return List<WorkDTO> 作品列表
     */
    @Override
    public List<WorkDTO> work(WorkDTO params) {
        String language =  params.getLanguage();
        Integer themeId =  params.getThemeId();
        List<WorkDTO> list;
        if ("en".equalsIgnoreCase(language)) {
            list = themeMapper.workEn(themeId);
        } else {
            list = themeMapper.work(themeId);
        }
        // 对 opusUrls 进行分割并赋值给 opusUrl
        for (WorkDTO work : list) {
            if (work.getOpusUrls() != null && !work.getOpusUrls().isEmpty()) {
                String[] urls = work.getOpusUrls().split(",");
                work.setOpusUrl(List.of(urls)); // 将数组转为 List
            } else {
                work.setOpusUrl(Collections.emptyList()); // 防止 null
            }
        }
        return  new ArrayList<>(list);
    }

    /**
     * 查询主题大赛总数
     * 逻辑说明：
     * 1. 根据dto参数统计主题大赛总数。
     *
     * @param dto 查询参数
     * @return int 主题大赛总数
     */
    @Override
    public int countCompetition(ThemeInfoDTO dto) {
        return themeMapper.countCompetition(dto);
    }

    /**
     * 查询当前主题大赛的所有作品总数
     * 逻辑说明：
     * 1. 根据dto参数统计作品总数。
     *
     * @param dto 查询参数
     * @return int 作品总数
     */
    @Override
    public int countTheme(WorkDTO dto) {
        return themeMapper.countTheme(dto);
    }

    /**
     * 查询所有已结束且排名状态为0（未计算）的主题ID
     * 逻辑说明：
     * 1. 查询所有已结束且未排名的主题ID，供定时任务自动排名使用。
     *
     * @return List<Integer> 主题ID列表
     */
    @Override
    public List<Integer> selectExpiredAndUnrankedThemes() {
        return themeMapper.selectExpiredAndUnrankedThemes();
    }

    /**
     * 更新主题的排名状态为1（已计算）
     * 逻辑说明：
     * 1. 根据themeId更新主题的排名状态，防止重复排名。
     *
     * @param themeId 主题ID
     * @return int 受影响的行数
     */
    @Override
    public int updateThemeRanked(Integer themeId) {
        return themeMapper.updateThemeRanked(themeId);
    }
}
